package org.lwjgl.demo.geometries;

import org.lwjgl.demo.device.TextureLoader;

import static org.lwjgl.opengl.ARBVertexArrayObject.glBindVertexArray;
import static org.lwjgl.opengl.GL11C.*;

/**
 * 球体
 *
 * @author zhoudy
 * @date 2025/10/29 21:50
 */
public class Sphere extends Mesh {
    private static final int STACKS = 16;
    private static final int SECTORS = 32;

    public Sphere() {
        generateSphere();
    }

    private void generateSphere() {
        float radius = 0.5f;
        float sectorStep = (float) (2 * Math.PI / SECTORS);
        float stackStep = (float) (Math.PI / STACKS);

        java.util.ArrayList<Float> verticesList = new java.util.ArrayList<>();
        java.util.ArrayList<Integer> indicesList = new java.util.ArrayList<>();

        // 生成顶点
        for (int i = 0; i <= STACKS; ++i) {
            float stackAngle = (float) (Math.PI / 2 - i * stackStep);
            float xy = radius * (float) Math.cos(stackAngle);
            float z = radius * (float) Math.sin(stackAngle);

            for (int j = 0; j <= SECTORS; ++j) {
                float sectorAngle = j * sectorStep;
                float x = xy * (float) Math.cos(sectorAngle);
                float y = xy * (float) Math.sin(sectorAngle);

                // 位置
                verticesList.add(x);
                verticesList.add(y);
                verticesList.add(z);

                // 颜色 (基于球面坐标)
//                verticesList.add((x + 0.5f));
//                verticesList.add((y + 0.5f));
//                verticesList.add((z + 0.5f));

                // 法线 (从球心指向表面的单位向量)
                float length = (float) Math.sqrt(x*x + y*y + z*z);
                verticesList.add(x / length);
                verticesList.add(y / length);
                verticesList.add(z / length);

                // 纹理坐标
                float s = (float) j / SECTORS;
                float t = (float) i / STACKS;
                verticesList.add(s);
                verticesList.add(t);
            }
        }

        // 生成索引
        for (int i = 0; i < STACKS; ++i) {
            int k1 = i * (SECTORS + 1);
            int k2 = k1 + SECTORS + 1;

            for (int j = 0; j < SECTORS; ++j, ++k1, ++k2) {
                if (i != 0) {
                    indicesList.add(k1);
                    indicesList.add(k2);
                    indicesList.add(k1 + 1);
                }
                if (i != (STACKS - 1)) {
                    indicesList.add(k1 + 1);
                    indicesList.add(k2);
                    indicesList.add(k2 + 1);
                }
            }
        }

        // 转换为数组
        float[] vertices = new float[verticesList.size()];
        for (int i = 0; i < verticesList.size(); i++) {
            vertices[i] = verticesList.get(i);
        }

        int[] indices = new int[indicesList.size()];
        for (int i = 0; i < indicesList.size(); i++) {
            indices[i] = indicesList.get(i);
        }

        setupMesh(vertices, indices);

        // ==================== 新增：为球体设置纹理 ====================
        try {
            // 球体使用纯色纹理或棋盘格纹理
            int diffuseTex = TextureLoader.createSolidColorTexture(100, 150, 200); // 蓝色
            if (diffuseTex != 0) {
                setDiffuseTexture(diffuseTex);
            }

            int specularTex = TextureLoader.createSolidColorTexture(100, 100, 100); // 灰色高光
            if (specularTex != 0) {
                setSpecularTexture(specularTex);
            }
        } catch (Exception e) {
            System.err.println("❌ 球体纹理加载失败: " + e.getMessage());
        }

    }

    @Override
    public void render() {
        // 绑定纹理
//        if (hasDiffuseTexture()) {
//            glActiveTexture(GL_TEXTURE0);
//            glBindTexture(GL_TEXTURE_2D, getDiffuseTexture());
//        }
//
//        if (hasSpecularTexture()) {
//            glActiveTexture(GL_TEXTURE1);
//            glBindTexture(GL_TEXTURE_2D, getSpecularTexture());
//        }

        glBindVertexArray(vao);
        glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);

//        glBindTexture(GL_TEXTURE_2D, 0);
    }
}
